#include <string>
#include <jsoncpp/json/json.h>

#include "sock/TcpSocket.hpp"
#include "UserManager.hpp"

enum REPLY{
  //注册成功
  REGISTERSUCCESS,
  //信息非法
  DIFICIENINFO,
  //用户存在
  USEREXIST,
  //登录成功
  LOGINSUCCESS,
  //账号或密码错误
  LOGINFAIL,
  //用户不存在
  USERNONEXIST
};

struct RegisterInfo{
  RegisterInfo(){
    memset(nick_name, 0, 128);
    memset(school, 0, 128);
    memset(pass_word, 0, 128);
  }

  char nick_name[128];
  char school[128];
  char pass_word[128];
};

struct LoginInfo{
  LoginInfo()
  :u_id(-1){
    memset(pass_word, 0, 128);
  }

  ID_Type u_id;
  char pass_word[128];
};

struct ReplyInfo{
  ID_Type u_id;
  REPLY reply;
};

const size_t sizeof_tcp_message = MAX_BUF_SIZE - sizeof(size_t) - 64;
const size_t sizeof_register_info = sizeof(RegisterInfo);
const size_t sizeof_login_info = sizeof(LoginInfo);
const size_t sizeof_reply_info = sizeof(ReplyInfo);
//为解决TCP粘包问题使用的自定义协议
//1. 用户的请求
//2. 登录或注册信息
class TcpMessage{
  public:
    TcpMessage()
    :msg_len(-1){
      memset(data, 0, sizeof(data));
    }

    TcpMessage(LoginInfo& info)
    :msg_len(sizeof_login_info){
      memset(data, 0, sizeof(data));
      memcpy(data, &info, sizeof_login_info);
      data[sizeof_login_info + 1] = '\r';
      data[sizeof_login_info + 2] = '\n';
    }

    TcpMessage(ReplyInfo& info)
    :msg_len(sizeof_reply_info){
      memset(data, 0, sizeof(data));
      memcpy(data, &info, sizeof_reply_info);
      data[sizeof_reply_info + 1] = '\r';
      data[sizeof_reply_info + 2] = '\n';
    }

    TcpMessage(RegisterInfo& info)
    :msg_len(sizeof_register_info){
      memset(data, 0, sizeof(data));
      memcpy(data, &info, sizeof_register_info);
      data[sizeof_register_info + 1] = '\r';
      data[sizeof_register_info + 2] = '\n';
    }

    void ToString(std::string& buf){
      buf.assign((char*)this, sizeof(TcpMessage));
    }
    
    size_t MsgLen(){
      return msg_len;
    }

    void* GetInfo(){
      return data;
    }

    bool Reply(TcpSocket* new_sock, UserManager* u_manager){
      ReplyInfo reply_message;
      std::string buf;
      if(msg_len == sizeof_register_info){
        RegisterInfo* info = (RegisterInfo*)data;
        UserInfo user(info->nick_name, info->school, info->pass_word);
        reply_message.u_id = user.GetUserID();
        if(u_manager->HaveRegister(user.GetUserID())){
          reply_message.reply = USEREXIST;
        }
        else if(u_manager->Register(user)){
          reply_message.reply = REGISTERSUCCESS;
        }
        else{
          reply_message.reply = DIFICIENINFO;
        }
      }
      else if(msg_len == sizeof_login_info){
        LoginInfo* info = (LoginInfo*)data;
        if(!u_manager->HaveRegister(info->u_id)){
          reply_message.reply = USERNONEXIST;
        }
        else if(u_manager->LoginOn(info->u_id, info->pass_word)){
          reply_message.u_id = info->u_id;
          reply_message.reply = LOGINSUCCESS;
        }
        else{
          reply_message.reply = LOGINFAIL;
        }
      }
      else{
        return false;
      }
      TcpMessage tmp(reply_message);
      tmp.ToString(buf);
      if(!new_sock->Send(buf)){
        LOG("");
        return false;
      }
      return true;
    }
  private:
    size_t msg_len;
    char data[sizeof_tcp_message];
};
